// 导航守卫  页面访问权限
// 需求：只有登录后才能访问系统中页面（除了登录和404页面之外）
// 我们只需要判断token是否存在即可，当token存在说已登录 否则未登录
import router from './router'
import store from './store'

// 全局前置导航守卫：本质上就是在路由页面跳转之前会触发的一个函数
router.beforeEach(async(to, from, next) => {
  /**
   * 当我们访问动态路由页面刷新浏览器的时候，所有数据都会被清空（token除外），此刻触发导航守卫的时候，
   * 导航守卫会立刻查找跳转的目标路由对象（也就是to的值），那此刻动态路由对象是不存在的(刷新被清空了)，
   *  那么导航守卫检测to值不存在的时候，会继续匹配其他的路由最终会匹配到404路由，那么此刻导航守卫会
   * 把to的值修改为404页面的路由对象
   * */
  //   console.log(from)
  // to: 跳转的目标路由对象
  // from: 当前的路由对象
  //   访问模块中变量的语法：store.state.模块名.变量名
  //   console.log(store.state.user.token)
  if (store.state.user.token) {
    // 已登录
    // 需求：当系统已经是登录状态了，那么不需要跳转到登录，如果访问的是登录页面重新跳转到首页即可
    if (to.path === '/login') {
      next('/')
    } else {
      // 获取用户信息
      // 页面跳转也会触发这里，但是只是页面跳转vuex数据是不会丢失的，因此没有必须再调用接口获取数据，
      // 只有刷新浏览器的时候会清空vuex数据，此刻才需要调用接口重新获取数据，那如何判断呢？
      // 答：我们只需判断userInfo对象是有数据即可
      if (!store.state.user.userInfo.userId) {
        // 注意：我们这里不能直接拿userInfo来判断，因为userInfo初始值是一个空对象
        // 而一个对象，无论是否存在属性都是true，因此不能直接拿它来判断
        // 因此我们可以拿对象里面的属性进行判断即可，我们这里拿userId来判断
        // 因此userId只要用户的登录并且获取到了用户信息，它的值就一定是存在的
        await store.dispatch('user/getUserInfo')
        // 调用筛选动态路由的函数，在这里获取动态路由的信息目的之一，
        // 就是为了保存能够获取到menus数组
        const menus = store.state.user.userInfo.roles.menus
        // 注意：调用筛选函数前面一定要加await才能接收到routes
        // 因为写在vuex的actions中的函数，会包装在一个promise对象中的
        const routes = await store.dispatch('permission/filterRoutes', menus)
        // 把筛选出来的动态路由 重新添加到路由规则中
        // 在最新的路由版本中addRoutes已废弃，但因为我们用的是花裤衩，
        // 用到还是比较旧版本的路由，所以还是要使用addRoutes方法。
        // const routes = store.state.permission.routes
        // 刷新浏览器会跳转到404页面
        // router.addRoutes(routes)
        // 解决方法：把404页面从静态路由中删除，然后把404和动态路由一起重新添加回路由规则中
        router.addRoutes([...routes, { path: '*', redirect: '/404', hidden: true }]) // 添加动态路由到路由表  铺路
        /**
         * 问题：此刻刷新浏览器页面出现空白。
         * 为什么呢？
         * 因为当我们刷新浏览器的时候数据会清空，导航守卫会查找to的值，此刻找不到访问的动态路由对象
         * 然后会继续匹配其他路由，又因404路由删除了，所以最终匹配不到任何的路由规则，最终to的值还是
         * 原来的动态路由对象（此刻是to空值，没有匹配到真正的动态路由对象的），所以放行后页面就会展示空白了
         * 怎么解决呢？
         * 答：重新跳转到当前的路由对象中即可
         * */
        return next(to.path)
      }
      next() // 放行函数
    }
  } else {
    // 未登录  跳转到登录页面4
    // 当访问的页面本来就是登录页面或者404页面的时候需要直接放行
    const writeArr = ['/login', '/404'] // 白名单，所有在白名单内的页面都可以直接访问
    // if (to.path === '/login' || to.path === '/404') { // 这种方式做判断，不利用扩展
    // 只需要判断到我们访问的目标路由路径 存在在白名单数组中即可说明该页面是可以直接访问的
    // includes方法 查找数组中是否存在某个元素，存在则返回true否则返回false
    if (writeArr.includes(to.path)) {
      next()
    } else {
      // 执行这行代码的时候会不会重新触发导航守卫 ？
      //  答：会，因为next方法传入路径是跳转，不是放行。
      next('/login')
    }
  }
})

